<template>
    <div ref="root" class="usage-rel-chart"></div>
  </template>
  
  <script setup>
  import * as echarts from 'echarts'
  import { ref, onMounted, onBeforeUnmount, watch, nextTick, defineExpose } from 'vue'
  
  const props = defineProps({
    /** 数据结构
     * {
     *   enableTime: '2024-01-10 08:00:00' | null,
     *   disableTime: '2024-05-20 18:00:00' | null,
     *   useSegments:  [{ dept:'生产部', start:'', end:'' }, ...],
     *   idleSegments: [{ start:'', end:'' }, ...]
     * }
     */
    data: { type: Object, default: () => ({}) },
    /** 容器高度：数字(像素)或字符串('50vh'|'420px') */
    height: { type: [Number, String], default: 420 }
  })
  
  const root = ref(null)
  let chart = null
  
  const COLORS = {
    use: '#4CAF50',
    idle: '#BDBDBD',
    stop: '#F56C6C',
    enableLine: '#409EFF',
    disableLine: '#F56C6C'
  }
  
  const px = v => (typeof v === 'number' ? `${v}px` : v)
  
  /** 兼容 Safari 的时间解析（空格 -> T） */
  function toMs(str) {
    if (!str) return null
    const s = String(str).replace(' ', 'T')
    const t = new Date(s).getTime()
    return Number.isFinite(t) ? t : null
  }
  function fmt(ts) {
    if (!ts) return '—'
    const d = new Date(ts)
    const p = n => String(n).padStart(2, '0')
    return `${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`
  }
  function durLabel(ms) {
    if (ms == null) return '—'
    const d = Math.floor(ms / 86400000)
    const h = Math.floor((ms % 86400000) / 3600000)
    return d ? `${d}天${h}小时` : `${h}小时`
  }
  
  function buildOption(d = {}) {
    const enable = toMs(d.enableTime)
    const disable = toMs(d.disableTime)
    const useSegs  = Array.isArray(d.useSegments)  ? d.useSegments  : []
    const idleSegs = Array.isArray(d.idleSegments) ? d.idleSegments : []
  
    const hasAny = !!enable || !!disable || useSegs.length > 0 || idleSegs.length > 0
  
    // ===== 空态：安全的最小配置 =====
    if (!hasAny) {
      return {
        grid: [{ left: 20, right: 20, top: 18, height: 140 }],
        xAxis: [{ type: 'time', gridIndex: 0 }],
        yAxis: [{ type: 'category', gridIndex: 0, data: ['设备'] }],
        series: [
          { type: 'custom', xAxisIndex: 0, yAxisIndex: 0, renderItem(){ return null }, data: [] }
        ],
        graphic: [{
          type: 'text', left: 'center', top: 'middle',
          style: { text: '暂无数据', fill: '#909399', fontSize: 16 }
        }]
      }
    }
  
    // ===== 顶部甘特条（custom）数据 =====
    const items = []
    for (const s of useSegs) {
      const st = toMs(s.start), ed = toMs(s.end)
      if (!st || !ed || ed <= st) continue
      items.push({
        name: '使用',
        value: [st, ed, s.dept || ''],
        itemStyle: { color: COLORS.use }
      })
    }
    for (const s of idleSegs) {
      const st = toMs(s.start), ed = toMs(s.end)
      if (!st || !ed || ed <= st) continue
      items.push({
        name: '闲置',
        value: [st, ed, '闲置'],
        itemStyle: { color: COLORS.idle }
      })
    }
  
    // ===== Sankey 数据（部门 -> 状态） =====
    const deptDur = new Map() // dept -> ms
    let idleMs = 0
    for (const s of useSegs) {
      const ms = Math.max(0, toMs(s.end) - toMs(s.start))
      if (!ms) continue
      deptDur.set(s.dept || '未知部门', (deptDur.get(s.dept || '未知部门') || 0) + ms)
    }
    for (const s of idleSegs) {
      idleMs += Math.max(0, toMs(s.end) - toMs(s.start))
    }
  
    const nodes = new Set(['设备', '使用', '闲置'])
    const links = []
    for (const [dept, ms] of deptDur) {
      nodes.add(dept)
      links.push({ source: dept, target: '使用', value: Math.round(ms / 3600000) })
    }
    if (idleMs > 0) links.push({ source: '设备', target: '闲置', value: Math.round(idleMs / 3600000) })
    const nodeList = Array.from(nodes).map(name => ({ name }))
  
    // ===== 布局 =====
    const topGrid = { left: 20, right: 20, top: 18, height: 140 }
    const bottomGridTop = topGrid.top + topGrid.height + 20
  
    return {
      tooltip: {
        trigger: 'item',
        confine: true,
        formatter: (p) => {
          if (p.seriesType === 'custom') {
            const [st, ed, dept] = p.value
            const ms = ed - st
            return `
              <div style="min-width:220px">
                <div><b>${p.name}</b> · ${dept || ''}</div>
                <div>开始：${fmt(st)}</div>
                <div>结束：${fmt(ed)}</div>
                <div>时长：${durLabel(ms)}</div>
              </div>
            `
          }
          if (p.seriesType === 'sankey') {
            return `${p.data.source || p.name} → ${p.data.target || ''}：<b>${p.value}</b> 小时`
          }
          return ''
        }
      },
  
      grid: [
        topGrid,
        { left: 10, right: 10, top: bottomGridTop, bottom: 10 }
      ],
  
      xAxis: [{ type: 'time', gridIndex: 0, axisLabel: { formatter: '{yyyy}-{MM}-{dd}' } }],
      yAxis: [{ type: 'category', gridIndex: 0, data: ['设备'], axisTick:{show:false}, axisLine:{show:false} }],
  
      series: [
        // 1) 顶部甘特 custom（矩形条）
        {
          type: 'custom',
          name: '时间轴',
          xAxisIndex: 0,
          yAxisIndex: 0,
          renderItem(params, api) {
            const start = api.value(0)
            const end   = api.value(1)
            const y     = api.coord([start, 0])[1]
            const x0    = api.coord([start, 0])[0]
            const x1    = api.coord([end,   0])[0]
            const height = Math.min(28, api.size([0, 1])[1] - 6)
            return {
              type: 'rect',
              shape: echarts.graphic.clipRectByRect(
                { x: x0, y: y - height/2, width: x1 - x0, height },
                { x: params.coordSys.x, y: params.coordSys.y, width: params.coordSys.width, height: params.coordSys.height }
              ),
              style: api.style({ radius: 4 })
            }
          },
          itemStyle: { opacity: 0.9 },
          encode: { x: [0, 1] },
          data: items
        },
  
        // 2) 启用/停用 标线（通过隐藏 scatter 的 markLine 实现）
        ...(enable ? [{
          type: 'scatter',
          xAxisIndex: 0, yAxisIndex: 0,
          data: [[enable, 0]],
          symbolSize: 0, silent: true, tooltip: { show: false },
          markLine: {
            symbol: ['none', 'triangle'],
            label: { position: 'insideEndTop', formatter: '启用', color: COLORS.enableLine },
            lineStyle: { color: COLORS.enableLine, type: 'solid' },
            data: [{ xAxis: enable }]
          }
        }] : []),
        ...(disable ? [{
          type: 'scatter',
          xAxisIndex: 0, yAxisIndex: 0,
          data: [[disable, 0]],
          symbolSize: 0, silent: true, tooltip: { show: false },
          markLine: {
            symbol: ['none', 'triangle'],
            label: { position: 'insideEndTop', formatter: '停用', color: COLORS.disableLine },
            lineStyle: { color: COLORS.disableLine, type: 'solid' },
            data: [{ xAxis: disable }]
          }
        }] : []),
  
        // 3) Sankey（仅在有 links 时绘制）
        ...(links.length ? [{
          type: 'sankey',
          top: bottomGridTop, left: 20, right: 20, bottom: 10,
          emphasis: { focus: 'adjacency' },
          draggable: true,
          lineStyle: { color: 'source', curveness: 0.5, opacity: 0.4 },
          label: { color: '#606266' },
          data: nodeList,
          links,
          levels: [
            { depth: 0, itemStyle: { color: '#90CAF9' } },
            { depth: 1, itemStyle: { color: COLORS.use } },
            { depth: 1, itemStyle: { color: COLORS.idle } },
            { depth: 1, itemStyle: { color: COLORS.stop } }
          ]
        }] : [])
      ]
    }
  }
  
  function render() {
    if (!root.value) return
    if (!chart) chart = echarts.init(root.value)
    chart.setOption(buildOption(props.data), true) // replaceMerge:全部
  }
  function resize() { chart && chart.resize() }
  defineExpose({ resize })
  
  onMounted(async () => {
    if (root.value) root.value.style.height = px(props.height)
    await nextTick()
    render()
    window.addEventListener('resize', resize)
  })
  onBeforeUnmount(() => {
    window.removeEventListener('resize', resize)
    chart && chart.dispose()
  })
  
  watch(() => props.data, render, { deep: true })
  watch(() => props.height, (h) => {
    if (root.value) {
      root.value.style.height = px(h)
      resize()
    }
  })
  </script>
  
  <style scoped>
  .usage-rel-chart { width: 100%; }
  </style>
  